package com.atguigu.gmall.activity.consumer;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.redis.CacheHelper;
import com.atguigu.gmall.activity.util.DateUtil;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.atguigu.gmall.rabbit.constant.MqConst;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * 接收秒杀相关活动信息
 */
@Component
public class ActivityConsumer {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    //半夜12点接收消息 ，叫秒杀表的数据导入缓存  当天的
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = MqConst.ROUTING_TASK_1
    ))
    public void seckillImportRedis(Message message, Channel channel){
        try {
            //将秒杀表的数据导入缓存（当天的数据）

            //4.查询
            QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper();
            //1.审核通过
            queryWrapper.eq("status",1);
            //3.必须有剩余库存的商品
            queryWrapper.gt("stock_count",0);
            //2.当天的商品
            queryWrapper.eq("DATE_FORMAT(start_time,'%Y-%m-%d')",
                    DateUtil.formatDate(new Date()));

            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(queryWrapper);
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                //当天有秒杀的商品
                seckillGoodsList.forEach(seckillGoods -> {
                    // 5.将结果集保存到Redis缓存中  Hash类型
                    //判断缓存是否存在
                    if (!redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_GOODS,
                            seckillGoods.getSkuId().toString())){
                        //作为秒杀新品放入缓存
                        redisTemplate.opsForHash().put(RedisConst.SECKILL_GOODS,
                                seckillGoods.getSkuId().toString(),seckillGoods);
                        //6.防止超卖  秒杀商品放到货架  用leftPush放的取得时候要用leftPop
                       redisTemplate.opsForList().leftPushAll(
                               RedisConst.SECKILL_STOCK_PREFIX + seckillGoods.getSkuId(),
                               buildSkuIds(seckillGoods.getSkuId(),seckillGoods.getStockCount()));
                        //7.状态位
                        //参数一：信道（队列名）
                        //参数二：消息 skuId:1    skuId:0
                        redisTemplate.convertAndSend("seckillpush",
                                seckillGoods.getSkuId() + ":1");
                    }

                });

            }

            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = MqConst.ROUTING_SECKILL_USER
    ))
    public void seckill(UserRecode userRecode,Message message, Channel channel){
        try {
            //校验状态位
            Object status = CacheHelper.get(userRecode.getSkuId().toString());
            if (!"1".equals(status)){
                return;
            }
            //用户是否来过    set之前判断是否已经存在
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(
                    RedisConst.SECKILL_USER + userRecode.getUserId(), "1");
            if (!flag){
                //来过
                return;
            }
            //Redis leftpop
            String skuId = (String) redisTemplate.opsForList().rightPop(
                    RedisConst.SECKILL_STOCK_PREFIX + userRecode.getSkuId());

            if (null == skuId){
                //没有  修改状态位
                redisTemplate.convertAndSend("seckillpush",
                        userRecode.getSkuId() + ":0");
                return;
            }
            //有   将资格保存在redis
            redisTemplate.opsForValue().set(RedisConst.SECKILL_ORDERS + userRecode.getUserId(),
                    userRecode.getSkuId());
            //收尾，更改库存
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //准备一个String数组，里面存放大量的skuId  String[] ids = {skuId,skuId,skuId....}
    public String[] buildSkuIds(Long skuId, Integer stock){
        String[] ids = new String[stock];
        for (Integer i = 0; i < stock; i++) {
            ids[i] = skuId.toString();
        }
        return ids;
    }

}
